package cn.jw.starter.common.utils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.lang3.StringUtils;

import cn.hutool.core.date.LocalDateTimeUtil;

/**
 * 唯一id生成工具类
 * 
 * @author 王广帅
 * @version 1.0.0
 * @since 2024/12/21 23:58
 */
public class JwUidUtil {
    private static final int MAX_INCR = 9000;
    private static final int START_INCR = 1000;
    private static AtomicInteger autoInc = new AtomicInteger(START_INCR);
    private static final String YYYY_MM_DD_HH_MM_SS = "yyyyMMddHHmmss";

    /**
     * 获取以日期开头的24位唯一id uid（21位） = yyyyMMddHHmmss(14位) + instanceId(3位) + 自增(4位)
     * 
     * @param instanceId
     *            服务的实例id
     * @return
     */
    public static String getDateUid(Integer instanceId) {
        return getDateUid(instanceId, 3);
    }

    /**
     * 获取以日期开头的唯一id uid长度 = yyyyMMddHHmmss(14位) + instanceId的instanceIdLen + 自增(4位)
     * 
     * @param instanceId
     * @param instanceIdLen
     * @return
     */
    public static String getDateUid(Integer instanceId, int instanceIdLen) {
        if (instanceId == null) {
            throw new NullPointerException("服务实例id不能为空");
        }
        String instanceIdStr = String.valueOf(instanceId);
        int instanceLen = instanceIdStr.length();
        if (instanceLen > instanceIdLen) {
            throw new IllegalArgumentException("服务实例id位数超长，最大: " + instanceIdLen);
        } else if (instanceLen < instanceIdLen) {
            instanceIdStr = StringUtils.leftPad(instanceIdStr, instanceIdLen, "0");
        }

        LocalDateTime localDateTime = LocalDateTime.now();
        String dateStr = LocalDateTimeUtil.format(localDateTime, DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS));
        StringBuilder strBuilder = new StringBuilder();
        int incr = autoInc.incrementAndGet();
        if (incr > MAX_INCR) {
            synchronized (autoInc) {
                incr = autoInc.incrementAndGet();
                if (incr > MAX_INCR) {
                    autoInc.set(START_INCR);
                }
            }
        }
        strBuilder.append(dateStr).append(instanceIdStr).append(autoInc.incrementAndGet());
        String uuid = strBuilder.toString();
        return uuid;
    }

    public static void main(String[] args) throws InterruptedException {
        Map<String, Integer> set = new ConcurrentHashMap<>();
        ExecutorService service = Executors.newFixedThreadPool(50);
        int size = 10000;
        CountDownLatch countDownLatch = new CountDownLatch(size);
        for (int i = 0; i < size; i++) {
            service.execute(() -> {
                String id = getDateUid(1001);
                set.put(id, 1);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        System.out.println(set.size());
        System.out.println(set.size() == size);
    }

}
